#include "include.h"

#if SPI1_AUDIO_EN

void spi1_irq_read(void);
void spi1_irq_tx(void);
/************************************************************
*SPI1单字节发送
************************************************************/
AT(.text.spiflash1_drv)
void spi1_sendbyte(u8 data)
{
    SPI1CON &= ~BIT(4);                             //TX
    SPI1BUF = data;
    while (!(SPI1CON & BIT(SPIPND)));                   //Wait pending
}
//SPI DMA发送 调用之前需要确定函数spi1_tx_init已初始化
AT(.text.spiflash1_drv)
void spi1_dma_sendbytes(void *data, u32 len)
{
    SPI1DMAADR = DMA_ADR(data);             //dac_obuf spi_recv_buf
    SPI1DMACNT = len;                       //DAC_OBUF_SIZE*4
}

/************************************************************
* SPI1发送初始化
* 发送可调用spi1_sendbyte
* 也可直接给用DMA配置先给数据地址，SPI1DMAADR = DMA_ADR(dac_obuf);
* 再给 SPI1DMACNT = DAC_OBUF_SIZE*4;
************************************************************/
AT(.text.spiflash1_drv)
void spi1_tx_init(u32 baud)
{
    //SPI1_G1: CLK_PA3, DO_PA4, DI PA5  //CS_PA5
    //SPI1_G3: CLK_PB1, DO_PB2 DI_PB0
    GPIOBFEN |= BIT(1)|BIT(2);
    GPIOBDE |=  BIT(1)|BIT(2);
    GPIOBDIR &= ~(BIT(1) | BIT(2));  //CLK,DO output
    FUNCMCON1 = (0x0F<<12);
    FUNCMCON1 = (SPI1G3<<12);  //G3
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    SPI1BAUD = 24000000/baud - 1;   //sys 24M.

#if SPI3WIREEN
	SPI1CON = BIT(SPIEN);
#else
    //
    SPI1CON =  BIT(SPIEN) | BIT(SPI_BUSMODE_LOWBIT) ;    //两线模式

    //查询发送测试
    /*
    printf("spi_send_test\n");
    WDT_DIS();
    SPI1BUF = 0x55;
    delay_5ms(1000);
    spi1_irq_tx();
    while(1) {
            //spi1_sendbyte(0x5A);
            //SPI1CON |= BIT(SPIPND);
            //SPI1BUF = 0xff;
            //SPI1DMAADR = DMA_ADR(spi_send_buf);
            //SPI1DMACNT = 4;
            delay_5ms(500);
            printf("->");
    }*/
#endif
	printf("[spi1_tx_mode:%d]\n", SPI1CON);
}
/*
AT(.com_text.timer)
void spi1_irq_handler(void)     //SPI1中断处理函数
{
    if(SPI1CON & BIT(SPIPND)){
        //SPI1CON &= BIT(SPIPND);
        //SPI1CON &= ~BIT(4);                             //TX
        SPI1BUF = 0x88;
        SPI1CON &= ~BIT(SPIIE);
        //SPI1BUF = i++;
        //
        printf("#");
    }
}

void spi1_irq_tx(void)
{
    SPI1CON |= BIT(SPI_RXSEL);
    SPI1CON |= BIT(SPIIE);
    sys_irq_init(IRQ_SPI_VECTOR,0,spi1_irq_handler);
    printf("WATI IRQ TX INT..\n");

    //WDT_DIS();
}*/



#if SPI1_RCV_EN
/************************************************************
*SPI1接收初始化
************************************************************/
AT(.text.spiflash1_drv)
void spi1_rx_init(void)
{
	u8 mode;
#if SPI3WIREEN
	mode = 0;		//三线模式交叉连线 SPI IN-OUT
#else
	mode = 2;		//两线模式直连 SPI IN-IN
#endif
	printf("spi_rx_mode:%d\n",mode);
	//SPI1_G1: CLK_PA3, DI_PA5
	//SPI1_G3: CLK_PB1, DI_PB0
	GPIOBFEN |= BIT(1)|BIT(mode);
	GPIOBDE  |=  BIT(1)|BIT(mode);		   //将PB2 PB3选中作为数字端口
	GPIOBDIR |= (BIT(1) | BIT(mode));		   //CLK,DO output		  //
	GPIOBPU |= BIT(1) | BIT(mode);	 //DI pull up 10K BIT(1) | BIT(2)
	FUNCMCON1 = (0x0F<<12);
	FUNCMCON1 = (SPI1G3<<12);


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //sys 24M. 接收无需设置波特率 由主机控制
    //SPI1BAUD = 24000000/baud - 1;
}

void obuf_put_samples_w(void *buf, uint len);//SPI1 中断入口函数
void dac_to_spi_enable(bool en);//设置DMA发送使能函数 1:使能 0：禁用

u8 spi_rxbuf_rear = 0;          //循环队列尾指针
u8 spi_rxbuf_front = 0;         //循环队列头指针

u32 dac_bufs[DAC_BUF_REV_MAX][DAC_OBUF_SPI_SIZE] AT(.dac_obuf);
extern u32 dac_obuf[576 + 512];
uint calc_crc(void *buf, uint len, uint seed);

/************************************************************
*循环队列缓冲判空
************************************************************/
AT(.text.spi1.proc)
u8 is_spi_rebuf_empty(void)
{
    if(spi_rxbuf_rear != spi_rxbuf_front){
        //printf("1y");
        return 0;
    }else{
        //printf("1n");        //缓冲区空
        return 1;
    }
}
/************************************************************
*循环队列缓冲判满
************************************************************/
AT(.text.spi1.proc)
u8 is_spi_rebuf_full(void)
{
    if(spi_rxbuf_front != (spi_rxbuf_rear + 1) % DAC_BUF_REV_MAX){
        //printf("2y");
        return 0;
    }else{
        //printf("2n");         //缓冲区满
        return 1;
    }
}
/************************************************************
*缓冲队列初始化
************************************************************/
AT(.text.spi1.proc)
void dac_bufs_init(void)
{
    u8 i;
    for(i = 0; i < DAC_BUF_REV_MAX ; i++){
        memset(dac_bufs[i], 0x00, DAC_OBUF_SPI_SIZE);
    }
    printf("[dac_bufs_init]\n");

}

AT(.text.spi1.proc)
void rev_send_2wire_test(void)
{
    u8 rev;
    rev = SPI1BUF;
    printf("<-%x",rev);
    spi1_sendbyte(0x68);
}


AT(.com_text.timer)
void spi1_irq_handler(void)     //SPI1中断处理函数
{
    if(SPI1CON & BIT(SPIPND)){
    #if SPI1DMAINT
		if(!is_spi_rebuf_full()){                                               //接收缓冲未满
            spi_rxbuf_rear = (spi_rxbuf_rear + 1) % DAC_BUF_REV_MAX;
            SPI1DMAADR = DMA_ADR(dac_bufs[spi_rxbuf_rear]);                      //设置SPI DMA接收地址
            SPI1DMACNT = DAC_OBUF_SPI_SIZE*4;                                    //SPI1DMACNT设置启动SPI接收
             //print_r(dac_bufs[spi_rxbuf_rear],128*4);
            //printf("*[spi_rxbuf_front = %d][spi_rxbuf_rear = %d]*\n",spi_rxbuf_front,spi_rxbuf_rear);
             //spi1_kick_start();                                                  //接收到数据立即激活音频处理函数
        }else{
            //printf("f");
        }
    #else
        //rev_send_2wire_test();
         u8 rev;
        rev = SPI1BUF;
        SPI1BUF = 0xFF;
        printf("<-%x",rev);
    #endif
    }
}


AT(.text.spiflash1_drv)
void spi1_irq_read(void)        // SPI1三线中断接收
{
    //中断接收SPI1控制寄存器设置：使能；从模式；中断使能;
    //三线模式下无需设置收发标记
#if SPI3WIREEN
    SPI1CON =  BIT(SPIEN) | BIT(SPISM) | BIT(SPIIE);
#elif SPI2WIREEN
	SPI1CON =  BIT(SPI_RXSEL) |BIT(SPI_BUSMODE_LOWBIT);
#endif
    sys_irq_init(IRQ_SPI_VECTOR,0,spi1_irq_handler);
    printf("WATI IRQ INT..\n");
    SPI1BUF = 0xff;
    //WDT_DIS();
    //while(1);
}

AT(.text.spiflash1_drv)
void spi1_dma_read(void *buf, u32 len) 				// SPI1三线DMA接收
{
    //DMA接收SPI1控制寄存器设置：使能；从模式；中断使能；
    //DMA和两线模式下需要设置接收标记位
    SPI1CON =  BIT(SPIEN)  | BIT(SPIIE) | BIT(SPI_RXSEL)| BIT(SPISM);
#if SPI2WIREEN
	SPI1CON |= BIT(SPI_BUSMODE_LOWBIT);				//两线模式;SPI_BUSMODE_LOWBIT
#endif
	//printf("SPI1CON = 0x%X\n",SPI1CON);
    SPI1DMAADR = DMA_ADR(buf); //dac_obuf spi_recv_buf
    //printf("SPI1DMAADR = 0x%X,0x%X\n",SPI1DMAADR,spi_recv_buf);
    SPI1DMACNT = len; //576*4
    sys_irq_init(IRQ_SPI_VECTOR,0,spi1_irq_handler);
    printf("WATI INT..\n");
    SPI1BUF = 0xff;
}




// SPI1三线查询接收
AT(.text.spiflash1_drv)
void spi1_check_read(void)
{
    SPI1CON =  BIT(SPIEN) | BIT(SPISM);
    SPI1BUF = 0xff;
    while(1){
        if(SPI1CON & BIT(SPIPND)){
            u8 r_dat = SPI1BUF;
            SPI1BUF = 0xff;
            printf("[0x%X,0x%X]",r_dat,SPI1CON);
        }

    }
}

/***************************************************************************
**func: SPI1 接收接口函数
**ref: mode:SPI_CHK_REV :查询接收
            SPI_IRQ_REV :中断单字节接收
            SPI_DMA_REV :中断DMA接收
***************************************************************************/
AT(.text.spiflash1_drv)
void spi1_read(u8 mode, void *buf, u32 len)
{
    spi1_rx_init();                                         //spi1初始化
    switch(mode){
        case SPI_CHK_REV: spi1_check_read();  break;       //查询
        case SPI_IRQ_REV: spi1_irq_read();    break;                  //    //中断
        case SPI_DMA_REV: spi1_dma_read(buf,len);break;    //DMA
        default: break;
    }

}
#endif



void music_data_mono_2_dual(u8 channel, void *dual_buf, void *mono_buf, u16 len);


/***************************************************************************
**spi1_play()  SPI音频播放
**
**
***************************************************************************/
AT(.text.spiflash1_drv)
void spi1_play(void)
{
    #if (SPI1_AUDIO_EN && SPI1_RCV_EN)
    sys_cb.vol = 4;                         //VOL_MAX/2
    bsp_change_volume(sys_cb.vol);          //设置音量
    dac_fade_in();                          //
    dac_spr_set(SPR_44100);                 //设置采样率 测试值44100可用 可根据实际情况调节
                                            //调节过低会导致SPI DMA 传输数据丢失
    spi1_read(SPI_DMA_REV,dac_bufs[spi_rxbuf_rear],DAC_OBUF_SPI_SIZE*4);    //SPI DMA 接收设置
    printf("[SPI AUDIO DATA RCV...]\n");
     WDT_DIS();
     while(1){
        u8 *buf=(u8*)&dac_obuf[DAC_OBUF_SIZE];
        //printf("[spi_rxbuf_front=%d][spi_rxbuf_rear=%d]\n",spi_rxbuf_front,spi_rxbuf_rear);
        if(!is_spi_rebuf_empty()){      //接收队列有数据则启动发送
        #if SPI1AUXEN
			music_data_mono_2_dual(0,buf,dac_bufs[spi_rxbuf_front],DAC_OBUF_SPI_SIZE*2);	//填充左声道
			music_data_mono_2_dual(1,buf,dac_bufs[spi_rxbuf_front],DAC_OBUF_SPI_SIZE*2);	//填充右声道
		#else
            memcpy((void*)buf, (void*)dac_bufs[spi_rxbuf_front], DAC_OBUF_SPI_SIZE*4);
		#endif
            obuf_put_samples_w(buf, DAC_OBUF_SPI_SIZE);
            GLOBAL_INT_DISABLE();      //关中断
            spi_rxbuf_front = (spi_rxbuf_front + 1) % DAC_BUF_REV_MAX;
            GLOBAL_INT_RESTORE();       //开中断
        }
        delay_us(500);                     //延迟500us正常
        //delay_ms(1);                    //1ms内测试正常 不加也可

     }
#elif (SPI1_AUDIO_EN && !SPI1_RCV_EN)
    printf("[SPI AUDIO DATA SEND...]\n");
#endif //SPI1_AUDIO_EN && SPI1_RCV_EN
}

#if SPI1_AUDIO_EN  && !SPI1_RCV_EN
/***************************************************************************
**蓝牙模式 dma 音频输出配置接口 （不能和dac_src0_onebyte_out_proc同时用）
***************************************************************************/
AT(.text.spiflash1_drv)
void dac_src0_dma_out_proc(void *buf, uint len)
{
    SPI1DMAADR = DMA_ADR(buf); 		//单声道：定义一个256字节的buf 将单声道数据提取出来存入并去DMA地址
    SPI1DMACNT = len*4;				//单声道：这里换成len*2
}                       //用户定义DMA输出（使用DMA则不用one byte发送）
/***************************************************************************
**蓝牙模式    one byte 音频输出配置接口 （）
**************************************************************************
AT(.text.spiflash1_drv)
void dac_src0_onebyte_out_proc(u32 aubufdata)
{

}                      //用户可定义SPI onebyte输出（使用one byte则不用DMA发送）*/
/***************************************************************************
** 蓝牙模式  音频输出 左右声道处理接口 （）
**************************************************************************
AT(.text.spiflash1_drv)
void dac_src0_drc_stereo_proc(s16 *left, s16 *right)
{

}                       //用户可处理左右声道数据*/
/***************************************************************************
**aux模式 音频输出配置接口 (单声道模式)
***************************************************************************/
#if SPI1AUXEN
AT(.text.spiflash1_drv)
void adadc_src0_dma_out_proc(void *buf, u32 len)
{
	//printf(".");
	SPI1DMAADR = DMA_ADR(buf);
	SPI1DMACNT = len*2;			//单声道数据
}
#endif

#endif

/***************************************************************************
**spi_send_test()  为SPI 测试函数
**spi_dacout_test()
**
***************************************************************************/
u32 spi_send_buf[4];

void spi_send_test(void)
{
    spi_send_buf[0]=0x6A7A8A9A;

    printf("spi_send_test\n");
    spi1_tx_init(2000000);
    WDT_DIS();
    while(1) {
        spi1_sendbyte(0x5A);
        //SPI1DMAADR = DMA_ADR(spi_send_buf);
        //SPI1DMACNT = 4;
        delay_5ms(40);
        printf("->");
    }
}



#if SPI1_RCV_EN

AT(.text.spiflash1_drv)
void spi_dacout_test(void)
{
    sys_cb.vol = VOL_MAX/2;
    bsp_change_volume(sys_cb.vol);
    dac_fade_in();
    dac_spr_set(SPR_22050); //SPR_48000 SPR_44100 SPR_38000
    //recv SPI audio data

    while(1){

        //obuf_put_samples_w(dac_obuf,576*4);
        //printf_info1();
        //AUCON0 &= ~BIT(26);
        //AUDMAADR = DMA_ADR(dac_obuf);
        /*
        SPI1CON |= BIT(4);
        SPI1DMAADR = DMA_ADR(dac_obuf);
        SPI1DMACNT = 576*4;
        while (!(SPI1CON & BIT(16)));           //Wait pending*/
        //print_r(dac_obuf,576*4);

        WDT_CLR();                              //watch dog

    }
}
#endif

#endif //SPI1_AUDIO_EN
